/*
 * 描          述:  <描述>
 * 修  改   人:  PengQingyang
 * 修改时间:  2024年3月10日
 * <修改描述:>
 */
package com.tx.core.starter.mybatis;

import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.tx.core.ddlutil.executor.TableDDLExecutor;
import com.tx.core.ddlutil.executor.TableDDLExecutorFactory;
import com.tx.core.exceptions.util.AssertUtils;
import com.tx.core.mybatis.config.MybatisPlusPropertiesCustomizer;
import com.tx.core.starter.component.*;
import org.hibernate.dialect.Dialect;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

/**
 * MybatisPlusAutoConfiguration前置执行类
 * 用以加载对Mybatis的扩展
 * <功能详细描述>
 *
 * @author PengQingyang
 * @version [版本号, 2024年3月10日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Configuration
@EnableConfigurationProperties(ComponentProperties.class)
@AutoConfigureBefore({MybatisPlusAutoConfiguration.class})
public class BeforeMybatisPlusAutoConfiguration implements InitializingBean {

    /** componentProperties */
    private ComponentProperties componentProperties;

    /** 数据源 */
    private DataSource dataSource;

    /** <默认构造函数> */
    public BeforeMybatisPlusAutoConfiguration(ComponentProperties componentProperties, DataSource dataSource) {
        super();

        this.componentProperties = componentProperties;
        if (this.componentProperties.getPersister() == null) {
            //设置组件属性持久层属性
            this.componentProperties.setPersister(new ComponentPersisterProperties());
        }

        this.dataSource = dataSource;
    }

    /**
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        AssertUtils.notNull(this.componentProperties, "componentProperties is null.");
        AssertUtils.notNull(this.componentProperties.getPersister(), "componentProperties.persister is null.");
        AssertUtils.notNull(this.componentProperties.getPersister().getDatabaseType(), "componentProperties.persister" +
                ".databaseType is null is null.");

        if (this.componentProperties.getPersister().getDialectClass() != null) {
            //为数据库类型装载匹配的方言实例
            Dialect newDialect =
                    this.componentProperties.getPersister().getDialectClass().getDeclaredConstructor().newInstance();
            DataBaseTypeRegistryUtils.setupDialect(this.componentProperties.getPersister().getDatabaseType(),
                    newDialect);
        }
    }

    /**
     * MybatisPlus中自定义属性写入<br/>
     *
     * @return
     */
    @Bean
    public MybatisPlusPropertiesCustomizer mybatisPlusPropertiesCustomizer() {
        MybatisPlusPropertiesCustomizer customizer = new MybatisPlusPropertiesCustomizer();
        return customizer;
    }


    /**
     * tableDDLExecutor
     *
     * @return
     */
    @Bean
    public TableDDLExecutorFactory tableDDLExecutor() {
        TableDDLExecutorFactory factory = new TableDDLExecutorFactory();
        factory.setDataSource(this.dataSource);
        factory.setDataSourceType(this.componentProperties.getPersister().getDatabaseType());

        return factory;
    }

    /**
     * tableInitializerExecutor
     *
     * @param tableDDLExecutor
     * @return
     */
    @ConditionalOnBean(TableDDLExecutor.class)
    @ConditionalOnProperty(prefix = ComponentConstants.PERSISTER_PROPERTIES_PREFIX,
            value = "table-auto-initialize", havingValue = "true")
    @Bean
    public TableInitializerExecutor tableInitializerExecutor(TableDDLExecutor tableDDLExecutor) {
        TableInitializerExecutor initializerExecutor = new TableInitializerExecutor(tableDDLExecutor,
                this.componentProperties.getPersister().isTableAutoInitialize());

        return initializerExecutor;
    }

    /**
     * Mybatis的分页拦截器
     *
     * @return
     */
    @Bean
    public PaginationInnerInterceptor paginationInnerInterceptor() {
        PaginationInnerInterceptor pii =
                new PaginationInnerInterceptor(this.componentProperties.getPersister().getDatabaseType().getDbType());
        return pii;
    }
}
